home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / DB_CLIPP / 0643A.ZIP / DATETIM.TXT < prev    next >
Text File  |  1987-04-24  |  22KB  |  633 lines

  1. Introduction
  2.  
  3. This month we present a series of assorted date and time routines that
  4. illustrate ways to handle dates for business calendar needs. Some are new and
  5. a number of others were published in previous issues of TechNotes.  We have
  6. brought them together to give a more authoritative list of techniques and
  7. programs.  We hope you find them useful.
  8.  
  9.  
  10. Setting the System DATE and TIME
  11.  
  12. There is no command in dBASE III or dBASE III PLUS to change the system time
  13. and date.  To change either or both of them, RUN the DOS programs DATE and
  14. TIME.  The desired date and time can be placed in a memory variable and passed
  15. to the operating system.  For example, 
  16.  
  17.    * ---Set DOS system date.
  18.    today = "11-01-86"
  19.    RUN DATE &today
  20.    
  21.    * ---Set DOS system time.
  22.    now = "08:00"
  23.    RUN TIME &now
  24.    
  25. Excerpted from the March, 1985 issue of TechNotes.
  26.  
  27.  
  28. Date Formatting
  29.  
  30. To create a custom date display, you can convert a date variable to a
  31. formatted string by using SUBSTR(), STR(), and date functions in combination. 
  32. If, for example, you have a date in and you want the output to look like
  33. "January 25, 1984," the expression that makes the conversion is,
  34.  
  35.    CMONTH(<date>) + " "  + STR(DAY(<date>),  2) +;
  36.                     ", " + STR(YEAR(<date>), 4)
  37.  
  38. In this expression, the first portion of the expression,
  39.  
  40.    CMONTH(<date>)
  41.  
  42. returns the month name as a character string.  The second portion of the
  43. expression,
  44.  
  45.    STR(DAY(<date>), 2)
  46.  
  47. returns the numeric day of the month as a character string.  The last portion
  48. of the expression,
  49.  
  50.    STR(YEAR(<date>), 4)
  51.  
  52. returns the year as a four-character string.  The results of this last
  53. expression are concatenated to the month and day.  This expression can be used
  54. as the field contents in a REPORT FORM, a LABEL FORM, or other display command
  55. that accepts a character expression such as ? or @...SAY.
  56.  
  57. General Date Formats
  58.  
  59. The following, Fdate.PRG, is a general purpose date formatting procedure.  It
  60. takes two inputs, a date variable to format and a numeric code designating the
  61. format desired, and produces one output, a character variable containing the
  62. formatted date string.  Call Fdate.PRG with the following general syntax.
  63.  
  64.    * ---Receiving variable must exist prior to call.
  65.    <return variable> = ""
  66.    DO Fdate WITH <date to format>,;
  67.                  <format code>,;
  68.                  <return variable>
  69.    
  70. Fdate.PRG supports several date formats.  Pick from the following list using
  71. the position in the list as the format code parameter when you DO Fdate.
  72.  
  73.    1. Mon DD, YYYY 
  74.    2. Mon YYYY
  75.    3. Mon DD
  76.    4. Month DD, YYYY
  77.    5. DD-Mon-YYYY
  78.    
  79. Note that the day format for formats 1, 3, and 4, do not include a leading
  80. zero.  If the day of the month is less than ten, the day will be a single
  81. digit number.  For format 5, the day format includes a leading zero for a day
  82. of the month less than ten.
  83.  
  84. * Program..: Fdate.PRG
  85. * Author...: Christopher White
  86. * Date.....: November 1, 1986
  87. *            published originally January 25, 1985
  88. * Version..: dBASE III PLUS
  89. * Note(s)..: This program takes a date variable passed to it
  90. *            with the PARAMETERS phrase and returns the date
  91. *            as a formatted character string.
  92. *
  93. PRIVATE ALL
  94. PARAMETERS date, code, datestrg
  95. DO CASE
  96. CASE code = 1
  97.      * ---"Nov 1, 1986"
  98.      datestrg = SUBSTR(CMONTH(date), 1, 3) + " "  +;
  99.                 LTRIM(STR(DAY(date), 2))   + ", " +;
  100.                 STR(YEAR(date), 4)
  101. CASE code = 2
  102.      * ---"Nov 1986"
  103.      datestrg = SUBSTR(CMONTH(date), 1, 3) + " " +;
  104.                 STR(YEAR(date), 4)
  105. CASE code = 3
  106.      * ---"Nov 1"
  107.      datestrg = SUBSTR(CMONTH(date), 1, 3) + " " +;
  108.                 LTRIM(STR(DAY(date), 2))
  109. CASE code = 4
  110.      * ---"November 1, 1986"
  111.      datestrg = CMONTH(date) + " " +;
  112.                 LTRIM(STR(DAY(date), 2)) + ", " + STR(YEAR(date), 4)
  113. CASE code = 5
  114.      * ---"01-Nov-1986"
  115.      datestrg = LEFT(DTOC(date), 2) + "-" +;
  116.                 SUBSTR(CMONTH(date), 1, 3) + "-" +;
  117.                 STR(YEAR(date), 4)
  118. OTHERWISE
  119.      datestrg = "Error"
  120. ENDCASE
  121. RETURN
  122. * EOP Fdate.PRG
  123.  
  124.  
  125. Excerpted from the March, 1985 issue of TechNotes.
  126.  
  127.  
  128. Working Days
  129.  
  130. Weekday1
  131.  
  132. The following two programs, Weekday1.PRG and Weekday2.PRG, show how to account
  133. for weekend days when determining a number of working days.  Weekday1.PRG
  134. allows you to select a start date and a number of days and will provide the
  135. number of working days inclusive. 
  136.  
  137. To setup Weekday1.PRG or Weekday2.PRG, first CREATE Holiday.DBF with the
  138. following structure,
  139.  
  140.    Structure for database: Holiday.DBF
  141.    Field  Field Name  Type       Width    Dec
  142.        1  Holiday     Date           8
  143.  
  144. Then, APPEND all the holidays that span the range of dates in which you will
  145. be working.  This means that if you are working with a span of two years, you
  146. must have APPENDed two records for each holiday, one for each specific date.  
  147.  
  148. To execute Weekday1.PRG, use the following general syntax after initializing a
  149. return variable for the number of weekdays. 
  150.  
  151.    ret_val = ""
  152.    DO Weekday1 WITH <start date>, <number of days>, ret_val
  153.    
  154. * Program ...: Weekday1.PRG
  155. * Author ....: Kenneth N. Getz
  156. * Date ......: November 1, 1986
  157. * Version ...: dBASE III PLUS
  158. * Note(s) ...: Program to find number of working days given
  159. *              a starting date and the numbers of days hence.
  160. *
  161. PRIVATE ALL
  162. PARAMETERS start, days, weekdays
  163. * ---Get starting date to be a week day.
  164. DO WHILE MOD(DOW(start) - 1, 6) = 0
  165.    start = start + 1
  166.    days  = days  - 1
  167. ENDDO
  168. * ---Subtract weekend days.
  169. weekdays = days - INT(days / 7) * 2
  170. * ---Find ending day. 
  171. endday = DOW(start + days - 1)
  172. * ---Subtract for each weekend day.
  173. IF MOD(endday - 1, 6) = 0
  174.    weekdays = IIF(endday = 1, weekdays - 2, weekdays - 1)
  175. ENDIF
  176. USE Holiday
  177. * ---Data file storing holidays.
  178. COUNT TO counter FOR  holiday >= start;
  179.                 .AND. holiday <= start + days;
  180.                 .AND. MOD(DOW(holiday) - 1, 6) <> 0
  181. USE
  182. * ---Subtract number of holidays.
  183. weekdays = weekdays - counter
  184. RETURN
  185. * EOP Weekday1.PRG
  186.  
  187.  
  188. Weekday2
  189.  
  190. Weekday2.PRG is a revision of Weekday1.PRG that allows you to specify a range
  191. of dates and returns the number of work days between them.  To execute
  192. Weekday2.PRG, use the following general syntax after initializing a return
  193. variable for the number of work days returned from the routine.
  194.  
  195.    ret_val = ""
  196.    DO Weekday2 WITH <start date>, <end date>, ret_val
  197.  
  198. * Program ...: Weekday2.PRG
  199. * Author ....: Kenneth N. Getz
  200. * Date ......: November 1, 1986 (Modified March 16, 1987)
  201. * Version ...: dBASE III PLUS
  202. * Note(s) ...: Program to find number of working days given
  203. *              a starting and ending date. Includes both end 
  204. *                     dates.
  205. *
  206. PRIVATE ALL
  207. PARAMETERS start, enddate, weekdays
  208. days = enddate - start + 1
  209. * ---Get starting date to be a week day.
  210. DO WHILE MOD(DOW(start) - 1, 6) = 0
  211.     start = start + 1
  212.       days  = days - 1
  213. ENDDO
  214. * ---Get ending date to be a week day.
  215. DO WHILE MOD(DOW(enddate) - 1,6) = 0
  216.     enddate = enddate - 1
  217.     days    = days - 1
  218. ENDDO    
  219. * ---Subtract off weekend days.
  220. weekdays = days - INT(days / 7) * 2
  221. USE Holiday
  222. COUNT TO counter FOR   holiday >= start;
  223.                  .AND. holiday <= start + days;
  224.                  .AND. MOD(DOW(holiday)-1,6) <> 0
  225. USE
  226. weekdays = weekdays - counter
  227. RETURN
  228. * EOP Weekday2.PRG
  229.  
  230.  
  231.  
  232. Twelve-Hour Time Format
  233.  
  234. If you find the standard twenty-four--hour clock confusing, you may want to
  235. use the following procedure, Ampm.PRG, to display the time in the more
  236. familiar twelve-hour format.
  237.  
  238. Ampm.PRG works by using the SUBSTR() function to separate the hours and
  239. minutes from the time string you pass.  These elements are then converted to
  240. the twelve-hour format.  To execute Ampm.PRG, use the following general syntax
  241. after initializing a return variable,
  242.  
  243.    ret_val = ""
  244.    DO Ampm WITH <time string>, ret_val
  245.    
  246. * Program ...: Ampm.PRG
  247. * Author ....: Ray Cortenbach and Kenneth N. Getz
  248. * Date ......: November 1, 1986
  249. * Note(s)....: Returns time in 12-hour format (midnight is am, *             
  250. noon is pm).
  251. *
  252. PRIVATE ALL
  253. PARAMETERS m_time, hours
  254. hours   = SUBSTR(m_time, 1, 2)
  255. minutes = SUBSTR(m_time, 3, 3)
  256. ampm    = IIF(hours >= "12"," pm"," am")
  257. clock_hours = MOD(VAL(hours),12)
  258. hours   = IIF(clock_hours = 0, "12", LTRIM(STR(clock_hours)))
  259. hours = hours + minutes + ampm
  260. RETURN
  261. * EOP Ampm.PRG
  262.  
  263. If you need this time format for a REPORT or LABEL FORM, you can use the
  264. following expression instead of Ampm.PRG.
  265.  
  266.    IIF(VAL(<time>) < 12, <time> + " am",;
  267.       IIF(VAL(<time>) = 12, <time> + " pm",;
  268.          STR(VAL(<time>) - 12 ,2) + SUBSTR(<time>, 3) + " pm"))
  269.  
  270.  
  271. Displaying Days
  272.  
  273. Another date format you may need is the form "Friday November 1st, 1986."  The
  274. following program converts a date to a character string and adds the
  275. appropriate "th", "st", "nd", "rd" to the day.  To execute Day.PRG, use the
  276. following general syntax after initializing a return variable.
  277.  
  278.    ret_val = ""
  279.    DO Day WITH <date>, ret_val
  280.  
  281. * Program ...: Day.PRG
  282. * Author ....: Ray Cortenbach and Kenneth N. Getz
  283. * Date ......: November 1, 1986
  284. * Note(s)....: Returns date in format "Friday November 1st, 1986"
  285. *
  286. PRIVATE ALL
  287. PARAMETERS m_date, current
  288. daynum = DAY(m_date)
  289. m_day  = LTRIM(STR(daynum, 2))
  290. DO CASE
  291. CASE daynum = 2 .OR. daynum = 22
  292.      m_day = m_day + "nd"
  293. CASE daynum = 3 .OR. daynum = 23
  294.      m_day = m_day + "rd"
  295. CASE MOD(daynum, 10) = 1 .AND. daynum <> 11
  296.      m_day = m_day + "st"
  297. OTHERWISE 
  298.      m_day = m_day + "th"
  299. ENDCASE
  300. current = CDOW(m_date) + " " + CMONTH(m_date) + " " +;
  301.           m_day + ", " + STR(YEAR(m_date), 4)
  302. RETURN
  303. * EOP Day.PRG
  304.  
  305.  
  306. Averaging Dates
  307.  
  308. Sometimes you may need to AVERAGE date fields in a database file.  For
  309. example, you may want to know the average date of employment for all employees
  310. or the average date of maturity for a group of bonds.
  311.  
  312. Since the date data type is handled differently in dBASE III PLUS than the
  313. numeric data type, the AVERAGE command does not support averaging of dates but
  314. does numerics.  To perform the AVERAGEing operation, you must convert the date
  315. fields you want to AVERAGE to a numeric values.  To do this, subtract one of
  316. the earliest dates in the dBASE III PLUS calendar, 01/01/0001 from your date
  317. field and then the result can then be AVERAGEd.  After AVERAGEing of the
  318. numeric values is complete, convert the result back to a date by adding it to
  319. the original date.  The following sequence of commands demonstrates how to do
  320. this:
  321.  
  322.    USE <database file>
  323.    AVERAGE <your date field> - CTOD("01/01/0001") TO avg
  324.    avgdate = CTOD("01/01/0001") + avg
  325.    
  326. You can also use this procedure that returns the average date from a date
  327. field that you pass as a parameter in place of these commands.  To execute it,
  328. use the following general syntax after initializing a return variable.
  329.  
  330.    ret_val = CTOD("01/01/01")
  331.    DO Dateavg WITH "<date field to average>", ret_val
  332.  
  333. * Program ...: Dateavg.PRG
  334. * Author ....: Brenda Johnson-Grau, based on a program
  335. *              by Steve Silverwood
  336. * Date ......: November 1, 1986
  337. * Note(s) ...: Procedure to return average of date field in a
  338. *              database file.
  339. *
  340. PRIVATE ALL
  341. PARAMETERS date_fld, avgdate
  342. AVERAGE &date_fld. - CTOD("01/01/0001") to avg
  343. avgdate = CTOD("01/01/0001") + avg
  344. RETURN
  345. * EOP Dateavg.PRG
  346.  
  347.  
  348. Calculating Ages
  349.  
  350. If you need to calculate and display a person's age according to the current
  351. date (rather than estimate from the year alone), you need to test both current
  352. month for the birth month and the current date for the birth date.  The
  353. following procedure, Age.PRG, takes a date passed to it and displays the
  354. person's age in the format: "x years old", where x is the calculated age.
  355.  
  356. * Program ...: Age.PRG
  357. * Author ....: Beth Miranda
  358. * Date ......: November 1, 1986
  359. * Note(s) ...: Calculates a person's age from today's date.
  360. * Version....: dBASE III
  361. *
  362. PARAMETERS birthdate
  363. age = 0
  364. currtmon = MONTH(DATE())
  365. birthmon = MONTH(birthdate)
  366. IF YEAR(DATE()) > YEAR(birthdate)
  367.    age = YEAR(DATE()) - YEAR(birthdate)
  368.    IF currtmon < birthmon .OR. ( currtmon = birthmon;
  369.                 .AND. DAY(DATE()) < DAY(birthdate))
  370.       age = age - 1
  371.    ENDIF
  372. ENDIF
  373. ? STR(age,4) + " years old"
  374. RETURN
  375. * EOP Age.PRG
  376.  
  377. In dBASE III PLUS, you can replace the program above with the following
  378. expression for use in REPORT and LABEL FORMs.
  379.  
  380.    ? IIF(YEAR(DATE())>YEAR(d2),;
  381.        IIF(MONTH(DATE())<MONTH(d2).OR.(MONTH(DATE())=MONTH(d2);
  382.            .AND.DAY(DATE())<DAY(d2)),;
  383.             YEAR(DATE())-YEAR(d2)-1,;
  384.             YEAR(DATE())-YEAR(d2);
  385.         ),;
  386.         0;
  387.      )
  388.    
  389. Be aware that this expression is 217 bytes long.  12 bytes are allocated for
  390. the "d2" variable name.  You can expand the variable name length to 10
  391. characters but the expression will be 253 characters, precariously close to
  392. the 254-character limit on the length of command lines.  If you plan to use
  393. this expression keep your date variable lengths short.
  394.  
  395.  
  396. Indexing Dates
  397.  
  398. INDEXing ON a date is quite easy.  For example, the command:
  399.  
  400.      INDEX ON <date field> TO <date index>
  401.  
  402. will produce an index in chronological order by year, month, and day.  
  403.  
  404. However, a problem arises when INDEXing ON a compound key that includes a date
  405. field which is common in the majority of applications.  A date is rarely the
  406. unique identifier or the sole determinant of order.  Suppose that you have a
  407. transaction-oriented application.  Typically, the transactions database file
  408. will be INDEXed ON the date of transaction and some form of customer
  409. identification.  The logical order is time-oriented, but the customer order
  410. must be maintained.  Or, the customer identification is the primary key and
  411. the date of transaction the secondary key--a type of ordering useful for
  412. invoicing, account history reporting, and aging analysis.  
  413.  
  414. Multiple Key Ascending Order
  415.  
  416. Defining an INDEX expression as a compound key requires that the key
  417. expression evaluate to a single data type.  In most instances, this data type
  418. will be character.  The character data type offers concatenation, a powerful
  419. tool to combine elements of an expression, which preserves a left-to-right
  420. precedence of order.
  421.  
  422. When defining a character expression that includes a date variable, your
  423. natural inclination might be to use DTOC() to convert the date field to a
  424. character string, and in most cases it would be a valid assumption.  INDEXing
  425. with the DTOC() function, however, does not yield a valid date order. 
  426. Instead, DTOC() returns as a character value, the date in the format specified
  427. by the SET DATE command.  The default is MM/DD/YY, the American format.  You
  428. could SET DATE ANSI and then INDEX ON the DTOC() of the date field, but this
  429. approach has its hazards.  In order to maintain the integrity of the index
  430. file, DATE must be SET ANSI whenever the index is updated.  However, the
  431. display format preferred in the United States is not ANSI.  A considerable
  432. amount of work would be required to make sure that every change to the
  433. database file is prefaced by a SET DATE ANSI and followed by a SET DATE
  434. AMERICAN for display operations.
  435.  
  436. The preferred method of INDEXing ON the date field with a compound key
  437. expression is to use the YEAR(), MONTH(), DAY(), and the STR() functions. 
  438. This will create the correct hierarchy of order, converting the date to a
  439. character string.  A example might look like,
  440.  
  441.    * ---Create index file.
  442.    INDEX ON STR(YEAR(Date),4) + STR(MONTH(Date),2);
  443.           + STR(DAY(Date),2) + Custnum TO DateNdx
  444.    
  445.    * ---Look up entry in the index file.
  446.    transdate = CTOD("  /  /  ")
  447.    customer  = SPACE(5)
  448.    @ 10,10 SAY "Enter transactions date " GET transdate
  449.    @ 11,10 SAY "  Enter customer number " GET customer
  450.    READ
  451.    SEEK STR(YEAR(transdate),4) + STR(MONTH(transdate),2);
  452.        + STR(DAY(transdate),2) + customer
  453.  
  454. Be sure that whenever you use STR() in an index expression, to specify a
  455. length parameter.  Failure to do so results in the error message "Record not
  456. in index" whenever the index file is used. 
  457.  
  458. Descending Order
  459.  
  460. INDEXing dates in descending order provides a new twist.  dBASE III and dBASE
  461. III PLUS does not directly support a descending order index file as dBASE II
  462. does.  Therefore, an algorithm must be devised to create a descending order
  463. and integrated with the date so that the hierarchy of order -- year, month,
  464. and day -- is preserved. 
  465.  
  466. In creating a descending order index file, the general idea is to subtract the
  467. key value from a number larger than the largest possible key value and pass
  468. that to the index mechanism as the new key value.  This reverses the order of
  469. keys, creating a descending order.  To use this algorithm, a date must be
  470. converted into a number that is in the form YYYYMMDD.  This can be done as
  471. follows:
  472.  
  473.    YEAR(<date>) * 10000 + MONTH(<date>) * 100 + DAY(<date>)
  474.  
  475. If today's date is 11/01/86, the result of the expression will be 19850801. 
  476. Notice that the integrity of the date is preserved and the result is in a form
  477. that can be subtracted from a very large number.
  478.  
  479. To INDEX a date in descending order, assemble the final algorithm and execute
  480. it in an INDEX command.  For example:
  481.  
  482.      INDEX ON STR(9999999 - (YEAR(<date>)*10000;
  483.            + MONTH(<date>)*100 + DAY(<date>)),8) TO <your index>
  484.  
  485. Essentially, INDEXing ON dates successfully requires some simple conversions
  486. and calculations. 
  487.  
  488. Excerpted from the August, 1985 issue of TechNotes.
  489.  
  490.  
  491. Scrolling Date Selectors
  492.  
  493. Introduction
  494.  
  495. Perhaps you would like to set up an application where you can easily select
  496. specific dates or periods.  The following programs, Scroll1.PRG and
  497. Scroll2.PRG, allow you to do this.  Each displays the date or date range in a
  498. reverse video window allowing you scroll forward or back in time with the
  499. Uparrow and Dnarrow keys.  Pressing Return selects the date or date period
  500. displayed.  Pressing Esc returns a blank or the seed date passed.  
  501.  
  502. For both programs, you pass the row and column coordinates of the scroll
  503. window and a return variable as parameters.
  504.  
  505.  
  506. Scroll Time Periods
  507.  
  508. Scroll1.PRG allows you to scroll through time periods beginning with the
  509. closest period to the system date.  The period begins on the closest Monday to
  510. the current date and ends on the Friday of the next week.  To change the
  511. length and the last day of the period, change the initial values of the memory
  512. variables "period" and "per_end". 
  513.  
  514. Pressing Esc returns a blank date.  Pressing Return, returns the beginning
  515. date of the time period your have selected.  
  516.  
  517. To execute Scroll1.PRG, use following commands,
  518.  
  519.    ret_val = CTOD("  /  /  ")
  520.    DO Scroll1 WITH <row>, <col>, ret_val
  521.  
  522. * Program ...: Scroll1.PRG
  523. * Author ....: Christopher White
  524. * Date ......: November 1, 1986
  525. * Note(s) ...: Selects a time period from a scrolling menu.
  526. *
  527. PRIVATE ALL
  528. PARAMETERS row, col, seed
  529. * ---Key definitions.
  530. esc      = CHR(27)
  531. uparrow  = CHR(5)
  532. dnarrow  = CHR(24)
  533. enter    = CHR(13)
  534. * ---Initialize dates.
  535. period  = 14
  536. per_end = period - 3
  537. start   = CTOD("01/08/1900")
  538. seed    = DATE() - (MOD(DATE() - start, period) + period)
  539. DO WHILE .T.
  540.    SET COLOR TO N/W
  541.    @ row, col SAY LEFT(CDOW(seed),3) + " "  + DTOC(seed)   +;
  542.                   " thru " + LEFT(CDOW(seed + per_end), 3) +;
  543.                   " " + DTOC(seed + per_end)
  544.    SET COLOR TO W/N
  545.    key = CHR(0)
  546.    * ---Get key.
  547.    DO WHILE .NOT. key $ esc + enter + dnarrow + uparrow
  548.       key = UPPER(CHR(INKEY()))
  549.    ENDDO
  550.    DO CASE
  551.    CASE key = dnarrow
  552.         seed = seed + period
  553.    CASE key = uparrow
  554.         seed = seed - period
  555.    CASE key = enter 
  556.         EXIT
  557.    CASE key = esc
  558.         seed = CTOD("  /  /  ")
  559.         EXIT
  560.    ENDCASE
  561. ENDDO
  562. RETURN
  563. * EOP Scroll1.PRG
  564.  
  565.  
  566. Scroll Days
  567.  
  568. Scroll2.PRG allows you to scroll through consecutive days beginning with the
  569. date you pass in the memory variable, "ret_val."  Pressing Return returns the
  570. date you selected in the variable "ret_val."  Pressing Esc, returns the seed
  571. date.  Subsequent runs of the program uses the last value stored in "ret_val"
  572. for the seed date.  This is useful so that you can carry forward selected
  573. dates.
  574.  
  575. To execute Scroll2.PRG, use the following commands.
  576.  
  577.    ret_val = DATE()
  578.    DO Scroll2 WITH <row>, <col>, ret_val
  579.  
  580. * Program ...: Scroll2.PRG
  581. * Author ....: Christopher White
  582. * Date ......: November 1, 1986
  583. * Note(s) ...: Selects a day from a scrolling menu.
  584. *
  585. PRIVATE ALL
  586. PARAMETERS row, col, seed
  587. * ---Key definitions.
  588. esc      = CHR(27)
  589. uparrow  = CHR(5)
  590. dnarrow  = CHR(24)
  591. enter    = CHR(13)
  592. * ---Initialize dates.
  593. start   = CTOD("01/08/1900")
  594. b_date  = seed
  595. DO WHILE .T.
  596.    SET COLOR TO N/W
  597.    @ row, col SAY LEFT(CDOW(seed),3)+" "+DTOC(seed)
  598.    SET COLOR TO W/N
  599.    key = CHR(0)
  600.    * ---Get key.
  601.    DO WHILE .NOT. key $ esc + enter + dnarrow + uparrow
  602.       key = UPPER(CHR(INKEY()))
  603.    ENDDO
  604.    DO CASE
  605.    CASE key = dnarrow
  606.         seed = seed + 1
  607.    CASE key = uparrow
  608.         seed = seed - 1
  609.    CASE key = enter
  610.         EXIT
  611.    CASE key = esc
  612.         seed = b_date
  613.         EXIT
  614.    ENDCASE
  615. ENDDO
  616. RETURN
  617. * EOP Scroll2.PRG
  618.  
  619.  
  620. Changing a Character Field to a Date Field
  621.  
  622. You can convert character fields that contain dates in the form "mm/dd/yy" or
  623. any of the formats specified by the SET DATE command to dBASE III PLUS date
  624. fields without losing the date value.  You do this by MODIFYing the STRUCTURE
  625. of the database file and changing the field that contians the date information
  626. from character to date type.  Saving this change converts all dates stored in
  627. the character field as "mm/dd/yy" directly to dBASE III PLUS date values.
  628.  
  629. This is useful when converting dBASE II database files to dBASE III PLUS.  
  630.  
  631. Excerpted from the February, 1985, issue of TechNotes.
  632.  
  633.